-module(client).
-export([start/1]).

-import(werkzeug,[get_config_value/2,logging/2,logstop/0,timeMilliSecond/0,to_String/1]).

%Start Funktion, einstieg ins Porgramm
start(Hostname) ->
		initialize(Hostname).

% get all values necessary for any client process
initialize(Hostname) ->		{ok, ConfigListe} = file:consult("client.cfg"),
							{ok, Lifetime} = werkzeug:get_config_value(lifetime, ConfigListe),
							{ok, Sendeintervall} = werkzeug:get_config_value(sendeintervall, ConfigListe),
							{ok, Servername} = werkzeug:get_config_value(servername, ConfigListe),
							{ok, Clients} = werkzeug:get_config_value(clients, ConfigListe),
							net_adm:ping(Hostname),
							spawnClients(Sendeintervall*1000, Servername,Lifetime*1000, Clients, Hostname).

% create the wanted count of client processes
spawnClients(_,_,_,0,_) -> ok;
spawnClients(Sendeintervall, Servername,Lifetime, Clients, Hostname) ->
		Clientname = string:concat("Client",string:concat(werkzeug:to_String(Clients),".log")),
		{ok,Clienthostname}=inet:gethostname(),
		%Logprefix setzt sich zusammen aus: "Client" Clientnummer@Hostname: 
		LogPrefix = lists:concat(["Client",Clients,"@",Clienthostname,": "]),
		ClientPID = spawn(fun() -> startClient(Sendeintervall, Servername, Clientname, LogPrefix, Hostname) end),
		timer:send_after(Lifetime, ClientPID, 'feierAbend'),
		spawnClients(Sendeintervall, Servername, Lifetime, Clients-1, Hostname).


% entering function for every client process
startClient(Sendeintervall, Servername, Clientname, LogPrefix, Hostname) -> Text = lists:concat([LogPrefix,"gestartet ",werkzeug:timeMilliSecond()]),
																  writeToLog(Clientname,Text),
																  Server={Servername,Hostname},
																  Server ! {getmsgid, self()},
																  editorRole(Clientname, LogPrefix, Sendeintervall, Server, 5,[]).


%logfile erstellen
writeToLog(MyLogFileName, Text) ->  werkzeug:logging(MyLogFileName, lists:concat([Text,"\r\n"])).

%berechnet neuen Sendeintervall und stellt sicher dass er nicht unter 1 fällt
berechneNeuenSendeintervall(Sendeintervall) -> 	round(case random:uniform(2) of
												1 when Sendeintervall*0.5 < 1000 -> 1000;
												1 -> Sendeintervall * 0.5;
												2 -> Sendeintervall * 1.5 end).
																		

%Leserrolle: schickt ein getmessages an den Server damit der Server alle verfügbaren Nachrichten für den Client an ihn schickt. Berechnet nach dem eingang der letzten Nachricht den Sendeintervall neu
readerRole(Clientname, LogPrefix, Sendeintervall,Server, EigeneNachrichten) ->
	Server ! {getmessages, self()},
	receive 	feierAbend -> 	writeToLog(Clientname, lists:concat(["Client fährt runter", werkzeug:timeMilliSecond()])),
								werkzeug:logstop(),
								bye;
				%weitere Nachrichten folgen, -_-_-_-_- Markierung bei Eingang von einer eigenen Nachricht
				{reply, Nummer,  Nachricht, false} -> Member= lists:member(Nummer,EigeneNachrichten),
													  if
													  Member == true ->  writeToLog(Clientname, lists:concat(["-_-_-_-_-",LogPrefix, Nachricht, " ","CIn: ",werkzeug:timeMilliSecond()]));
													  Member == false -> writeToLog(Clientname, lists:concat([LogPrefix, Nachricht, " ","CIn: ",werkzeug:timeMilliSecond()]))
													  end,
													  readerRole(Clientname, LogPrefix, Sendeintervall,Server, EigeneNachrichten);
				%Letzte Nachricht, $$$$ Markirerung bei Eingang der eigenen Nachricht
				{reply, Nummer,  Nachricht, true} ->  Member= lists:member(Nummer,EigeneNachrichten),
													  if
													  Member == true ->  writeToLog(Clientname, lists:concat(["-_-_-_-_-",LogPrefix,Nachricht, " ","CIn: ",werkzeug:timeMilliSecond()]));
													  Member == false -> writeToLog(Clientname, lists:concat([LogPrefix, Nachricht," ","CIn: ",timeMilliSecond()]))
													  end,
													  writeToLog(Clientname,"Alle Nachrichten abgerufen"),
													  NeuerSendeIntervall = berechneNeuenSendeintervall(Sendeintervall),
													  writeToLog(Clientname, lists:concat(["Neuer Sendeintervall: ",NeuerSendeIntervall])),
													  Server ! {getmsgid, self()},
													  editorRole(Clientname, LogPrefix, NeuerSendeIntervall,Server,5, EigeneNachrichten)
	end.



%Redakterurolle: Sendet in einen Intervall 5 Nachrichten an den Server, frag eine 6te msgID an und wechselt in die Leserrolle
editorRole(Clientname, LogPrefix, Sendeintervall,Server, Sendeanzahl, EigeneNachrichten) ->
	receive   	{nnr, Nummer} -> 
								 if
								 Sendeanzahl /= 0 ->	timer:send_after(Sendeintervall, 'sendeNeueNachricht'), 
														{_,Hostname}=inet:gethostname(),
														%Nachricht zusammenbauen. Format: Logprefix(siehe oben) Hostname -03-15(unsere Kennung) Xte Nachricht COut Timestamp
														NeueEigeneNachrichten = lists:append(EigeneNachrichten,[Nummer]),
														Nachricht= lists:concat([LogPrefix,Hostname,"-03-15: ",Nummer,"te Nachricht","COut: ", werkzeug:timeMilliSecond()]),
														Server ! {dropmessage, {Nachricht, Nummer}},
														writeToLog(Clientname,Nachricht),
														editorRole(Clientname, LogPrefix, Sendeintervall, Server, Sendeanzahl-1, NeueEigeneNachrichten);
								 Sendeanzahl == 0 ->  	writeToLog(Clientname,lists:concat([Nummer,"te Nachricht vergessen"])),
														readerRole(Clientname, LogPrefix, Sendeintervall,Server, EigeneNachrichten)
								 end;
				sendeNeueNachricht ->	Server ! {getmsgid, self()},
										editorRole(Clientname, LogPrefix, Sendeintervall, Server, Sendeanzahl, EigeneNachrichten);
				feierAbend ->   writeToLog(Clientname, lists:concat(["Client fährt runter", werkzeug:timeMilliSecond()])),
				werkzeug:logstop(),
						bye 
	end.

